package middleware

import (
	"fmt"
	"net/http"
	"regexp"
	"strings"
)

// node 路由树节点
type node struct {
	// 静态路由
	children map[string]*node
	// 正则路由-只能有一个
	regChild *node
	// 路径参数路由
	pathChild *node
	// 通配符路由
	wildChild *node
	// 执行逻辑
	handler HandleFunc
	// 正则匹配
	reg *regexp.Regexp
	// 路径参数名称
	pathName string
	// 保存path
	path string
	// 中间件
	middlewares []HandleFunc
	// HandleFunc
	hander HandleFunc
}

type GCtx struct {
	Request *http.Request
	Params  map[string]string
	writer  http.ResponseWriter
}

func (this *GCtx) WriteString(s string) {
	this.writer.Write([]byte(s))
}

type HandleFunc func(ctx *GCtx)

// addMiddleware 添加中间件
func (n *node) addMiddleware(path string, fn HandleFunc) {
	// 不支持以/结尾的路由 处分是根路径
	if len(path) > 1 && path[len(path)-1] == '/' {
		panic("path not support / end")
	}

	path = strings.TrimSuffix(path, "/")

	paths := strings.Split(path, "/")

	if n.children == nil {
		n.children = make(map[string]*node)
	}

	// 添加根节点
	child, ok := n.children[""]

	// 如果根节点不存在
	if !ok {
		child = &node{}
		n.children[""] = child
	}

	// 如果是跟节点
	if path == "" {
		child.middlewares = append(child.middlewares, fn)
	}

	// 递归添加
	child.addMiddlewareRecursion(paths[1:], fn)
}

func (n *node) addMiddlewareRecursion(paths []string, fn HandleFunc) {
	if len(paths) == 0 {
		return
	}

	path := paths[0]

	if path == "" {
		panic("path not support empty")
	}

	paths = paths[1:]

	// 只支持静态、路径参数、通配符，不支持正则
	switch path[0] {
	case '(': // 正则
		panic("add middleware failed:path not support regexp")
	case ':': // 路径参数
		if n.pathChild == nil {
			n.pathChild = &node{}
		}

		if len(paths) == 0 {
			n.pathChild.middlewares = append(n.pathChild.middlewares, fn)
		} else {
			n.pathChild.addMiddlewareRecursion(paths, fn)
		}

	case '*': // 通配符
		if n.wildChild == nil {
			n.wildChild = &node{}
		}

		if len(paths) == 0 {
			n.wildChild.middlewares = append(n.wildChild.middlewares, fn)
		} else {
			n.addMiddlewareRecursion(paths, fn)
		}

	default:

		if n.children == nil {
			n.children = make(map[string]*node)
		}

		child, ok := n.children[path]

		if !ok {
			child = &node{}
		}

		if len(paths) == 0 {
			child.middlewares = append(child.middlewares, fn)
		} else {
			child.addMiddlewareRecursion(paths, fn)
		}

		n.children[path] = child
	}
}

// findMiddleware 查找中间件，尽可能多的匹配
func (n *node) findMiddleware(path string) []HandleFunc {
	paths := strings.Split(path, "/")

	// 递归查找
	if n.children == nil {
		return nil
	}

	root, ok := n.children[""]

	if !ok {
		return nil
	}

	var result []HandleFunc

	if len(root.middlewares) > 0 {
		result = root.middlewares
	}

	// 递归查找
	return append(result, root.findMiddlewareRecursion(paths[1:])...)
}

// findMiddlewareRecursion 递归查找中间件
func (n *node) findMiddlewareRecursion(paths []string) []HandleFunc {
	if len(paths) == 0 {
		return nil
	}

	path := paths[0]

	if path == "" { // 空路径
		return nil
	}

	paths = paths[1:]

	var result []HandleFunc

	// 查找静态路由
	if child, ok := n.children[path]; ok {
		if len(paths) == 0 {
			result = append(result, child.middlewares...)
		} else {
			result = append(result, child.findMiddlewareRecursion(paths)...)
		}
	}

	// 查找*通配符
	if n.wildChild != nil {
		if len(paths) == 0 {
			result = append(result, n.wildChild.middlewares...)
		} else {
			result = append(result, n.wildChild.findMiddlewareRecursion(paths)...)
		}
	}

	// 查找:路径参数
	if n.pathChild != nil {
		if len(paths) == 0 {
			result = append(result, n.pathChild.middlewares...)
		} else {
			result = append(result, n.pathChild.findMiddlewareRecursion(paths)...)
		}
	}

	return result
}

func (n *node) addRoute(path string, fn HandleFunc) {
	// 不支持以/结尾的路由 处分是根路径
	if len(path) > 1 && path[len(path)-1] == '/' {
		panic("path not support / end")
	}

	path = strings.TrimSuffix(path, "/")

	paths := strings.Split(path, "/")

	if n.children == nil {
		n.children = make(map[string]*node)
	}

	// 添加根节点
	child, ok := n.children[""]

	// 如果根节点不存在
	if !ok {
		child = &node{}
		n.children[""] = child
	}

	// 如果是跟节点
	if path == "" {
		child.handler = fn
	}

	// 递归添加
	child.addRouteRecursion(paths[1:], fn)
}

func (n *node) addRouteRecursion(paths []string, fn HandleFunc) {
	if len(paths) == 0 {
		return
	}

	path := paths[0]

	if path == "" {
		panic("path not support empty")
	}

	paths = paths[1:]

	// 只支持静态、路径参数、通配符，不支持正则
	switch path[0] {
	case '(': // 正则
		panic("add route failed:path not support regexp")
	case ':': // 路径参数
		if n.pathChild == nil {
			n.pathChild = &node{}
		}

		n.pathChild.path = path[1:]

		if len(paths) == 0 {
			n.pathChild.handler = fn
		} else {
			n.pathChild.addRouteRecursion(paths, fn)
		}

	case '*': // 通配符
		if n.wildChild == nil {
			n.wildChild = &node{}
		}

		n.wildChild.path = "*"

		if len(paths) == 0 {
			n.wildChild.handler = fn
		} else {
			n.addRouteRecursion(paths, fn)
		}
	default:
		if n.children == nil {
			n.children = make(map[string]*node)
		}

		child, ok := n.children[path]

		if !ok {
			child = &node{}
			n.children[path] = child
		}

		child.path = path

		if len(paths) == 0 {
			child.handler = fn
		} else {
			child.addRouteRecursion(paths, fn)
		}
	}
}

// findRoute 查找路由
func (n *node) findRoute(path string, ctx *GCtx) *node {
	paths := strings.Split(path, "/")

	// 递归查找
	if n.children == nil {
		return nil
	}

	root, ok := n.children[""]

	if !ok {
		return nil
	}

	if path == "" {
		return root
	}

	// 递归查找
	return root.findRouteRecursion(paths[1:], ctx)
}

func (n *node) findRouteRecursion(paths []string, ctx *GCtx) *node {
	if len(paths) == 0 {
		return nil
	}

	path := paths[0]

	if path == "" {
		return nil
	}

	paths = paths[1:]

	// 查找静态路由
	if child, ok := n.children[path]; ok {
		if len(paths) == 0 {
			return child
		}

		return child.findRouteRecursion(paths, ctx)
	}

	// 查找*通配符
	if n.wildChild != nil {
		if len(paths) == 0 {
			return n.wildChild
		}

		return n.wildChild.findRouteRecursion(paths, ctx)
	}

	// 查找:路径参数
	if n.pathChild != nil {
		if len(paths) == 0 {
			return n.pathChild
		}

		ctx.Params[n.pathChild.path] = path

		return n.pathChild.findRouteRecursion(paths, ctx)
	}

	return nil
}

type Server struct {
	// 路由树
	router *Router
	// 中间件
	middlewares *Router
}

// NewServer 创建服务
func NewServer() *Server {
	return &Server{
		router:      NewRouter(),
		middlewares: NewRouter(),
	}
}

// Router 路由树
type Router struct {
	// GET root node
	rootGET *node
	// POST root node
	rootPOST *node
	// PUT root node
	rootPUT *node
	// DELETE root node
	rootDELETE *node
	// HEAD
	rootHEAD *node
	// OPTIONS
	rootOPTIONS *node
	// CONNECT
	rootCONNECT *node
	// TRACE
	rootTRACE *node
	// PATCH
	rootPATCH *node
}

// NewRouter 创建路由树
func NewRouter() *Router {
	return &Router{
		rootGET:     &node{},
		rootPOST:    &node{},
		rootPUT:     &node{},
		rootDELETE:  &node{},
		rootHEAD:    &node{},
		rootOPTIONS: &node{},
		rootCONNECT: &node{},
		rootTRACE:   &node{},
		rootPATCH:   &node{},
	}
}

// Use 添加中间件
func (s *Server) Use(method string, path string, fn HandleFunc) {
	switch method {
	case http.MethodGet:
		s.middlewares.rootGET.addMiddleware(path, fn)
	case http.MethodPost:
		s.middlewares.rootPOST.addMiddleware(path, fn)
	case http.MethodPut:
		s.middlewares.rootPUT.addMiddleware(path, fn)
	case http.MethodDelete:
		s.middlewares.rootDELETE.addMiddleware(path, fn)
	case http.MethodPatch:
		s.middlewares.rootPATCH.addMiddleware(path, fn)
	case http.MethodHead:
		s.middlewares.rootHEAD.addMiddleware(path, fn)
	case http.MethodOptions:
		s.middlewares.rootOPTIONS.addMiddleware(path, fn)
	case http.MethodConnect:
		s.middlewares.rootCONNECT.addMiddleware(path, fn)
	case http.MethodTrace:
		s.middlewares.rootTRACE.addMiddleware(path, fn)
	default:
		panic("method not support")
	}
}

// findMiddleware 查找中间件
func (s *Server) findMiddleware(method string, path string) []HandleFunc {
	switch method {
	case http.MethodGet:
		return s.middlewares.rootGET.findMiddleware(path)
	case http.MethodPost:
		return s.middlewares.rootPOST.findMiddleware(path)
	case http.MethodPut:
		return s.middlewares.rootPUT.findMiddleware(path)
	case http.MethodDelete:
		return s.middlewares.rootDELETE.findMiddleware(path)
	case http.MethodPatch:
		return s.middlewares.rootPATCH.findMiddleware(path)
	case http.MethodHead:
		return s.middlewares.rootHEAD.findMiddleware(path)
	case http.MethodOptions:
		return s.middlewares.rootOPTIONS.findMiddleware(path)
	case http.MethodConnect:
		return s.middlewares.rootCONNECT.findMiddleware(path)
	case http.MethodTrace:
		return s.middlewares.rootTRACE.findMiddleware(path)
	default:
		return nil
	}
}

// AddRoute 添加路由
func (s *Server) AddRoute(method string, path string, fn HandleFunc) {
	switch method {
	case http.MethodGet:
		s.router.rootGET.addRoute(path, fn)
	case http.MethodPost:
		s.router.rootPOST.addRoute(path, fn)
	case http.MethodPut:
		s.router.rootPUT.addRoute(path, fn)
	case http.MethodDelete:
		s.router.rootDELETE.addRoute(path, fn)
	case http.MethodPatch:
		s.router.rootPATCH.addRoute(path, fn)
	case http.MethodHead:
		s.router.rootHEAD.addRoute(path, fn)
	case http.MethodOptions:
		s.router.rootOPTIONS.addRoute(path, fn)
	case http.MethodConnect:
		s.router.rootCONNECT.addRoute(path, fn)
	case http.MethodTrace:
		s.router.rootTRACE.addRoute(path, fn)
	default:
		panic("method not support")
	}
}

// findRoute 查找路由
func (s *Server) findRoute(method string, path string, ctx *GCtx) *node {
	switch method {
	case http.MethodGet:
		return s.router.rootGET.findRoute(path, ctx)
	case http.MethodPost:
		return s.router.rootPOST.findRoute(path, ctx)
	case http.MethodPut:
		return s.router.rootPUT.findRoute(path, ctx)
	case http.MethodDelete:
		return s.router.rootDELETE.findRoute(path, ctx)
	case http.MethodPatch:
		return s.router.rootPATCH.findRoute(path, ctx)
	case http.MethodHead:
		return s.router.rootHEAD.findRoute(path, ctx)
	case http.MethodOptions:
		return s.router.rootOPTIONS.findRoute(path, ctx)
	case http.MethodConnect:
		return s.router.rootCONNECT.findRoute(path, ctx)
	case http.MethodTrace:
		return s.router.rootTRACE.findRoute(path, ctx)
	default:
		return nil
	}
}

// ServeHTTP 实现http.Handler接口
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	ctx := &GCtx{
		writer:  w,
		Request: r,
		Params:  make(map[string]string),
	}

	// 查找路由
	route := s.findRoute(r.Method, r.URL.Path, ctx)
	fmt.Println(r.Method, r.URL.Path, route)
	if route == nil {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// 查找中间件
	middlewares := s.findMiddleware(r.Method, r.URL.Path)
	// 执行中间件
	for _, middleware := range middlewares {
		middleware(ctx)
	}

	fmt.Println("route:", route)
	// 执行路由
	route.handler(ctx)
}
